package com.joymart.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.joymart.common.system.rest.authority.RestAuthorityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.Optional;

@Configuration
@EnableWebSecurity
public class SecurityConfig {


    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private BearerTokenAuthenticationFilter bearerTokenAuthenticationFilter;
    @Autowired
    private RestAuthorityService restAuthorityService;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        return http.csrf(csrf -> csrf.disable())
                .authorizeHttpRequests((authorizeHttpRequests) ->{
                            //注意这里，先声明的具有高优先级。
                             applyRestAuthorities(authorizeHttpRequests);
                             authorizeHttpRequests
                                    .requestMatchers(HttpMethod.POST,
                                            "/login",
                                            "/signup").permitAll()
                                    .requestMatchers(HttpMethod.GET,
                                            "/dictionaries/**",
                                            "/protocols/user_protocol/latest",
                                            "/carousel/items",
                                            "/activityCard/items",
                                            "/error").permitAll()
                                    .requestMatchers(HttpMethod.GET, "/products", "/products/*").permitAll()
                                    .requestMatchers("/admin/**").hasAuthority("ROLE_PARTY_A")
//                                .requestMatchers("/wechat/**").permitAll()
                                    .requestMatchers("/**").authenticated();

                        }

                )
                .cors(cors->{})
                .httpBasic(basic -> basic.disable())
                .formLogin(formLogin -> formLogin.disable())
                .anonymous(anonymous -> anonymous.disable())
                .exceptionHandling(errorHandling -> errorHandling.accessDeniedHandler(accessDeniedHandler()))
                .sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .addFilterBefore(bearerTokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    private void applyRestAuthorities(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry registry) {
        restAuthorityService.findAll().forEach(
                authority -> {
                         // todo
                }
        );
    }

    // Password Encoding
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new Argon2PasswordEncoder(16, 32, 1, 16384, 2);
    }


    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return (request, response, accessDeniedException) -> {
            response.setCharacterEncoding("UTF-8");
            Optional<Object> tokenIssue = Optional.ofNullable(request.getAttribute("TOKEN_ISSUE"));
            if (tokenIssue.isPresent()) {
                response.getWriter().println(objectMapper.writeValueAsString(Map.of("message",tokenIssue.get())));
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
            } else {
                response.getWriter().println(objectMapper.writeValueAsString(Map.of("message","您不具有相关权限")));
                response.setStatus(HttpStatus.FORBIDDEN.value());
            }

        };

    }

}
